package org.dromara.work.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.tokenizer.engine.word.WordResult;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.exception.base.BaseException;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysUserService;
import org.dromara.work.domain.*;
import org.dromara.work.domain.bo.DmBaseComplexSaveBo;
import org.dromara.work.domain.bo.DmBaseQueryBo;
import org.dromara.work.domain.bo.DmGeoSaveBo;
import org.dromara.work.domain.vo.*;
import org.dromara.work.mapper.*;
import org.dromara.work.service.IDmBaseService;
import org.dromara.work.service.ISpatialAttrBaseService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Author Chen
 * CreateTime 2024/1/15 10:09
 */
@Service
@RequiredArgsConstructor
public class IDmBaseServiceImpl implements IDmBaseService {


    private final DmBaseMapper dmBaseMapper;

    private final BaseDmlbMapper dmlbMapper;

    private final DmGeoMapper geoMapper;

    private final DmFjMapper fjMapper;

    //命名文件
    private final DmNameFileCodeMapper nameFileMapper;

    private final DmTemplateMapper templateMapper;

    private final ISysUserService userService;

    @Override
    public TableDataInfo<DmBaseBriefVo> customPageList(DmBaseQueryBo bo, PageQuery pageQuery) {
        SysUserVo user= userService.selectUserById(LoginHelper.getUserId());
        if(StringUtils.isBlank(bo.getXzqh())){
            if(user.getXzqh()!=null){
                bo.setXzqh(user.getXzqh());
            }
        }
        LambdaQueryWrapper<DmBase> lqw = buildQueryWrapper(bo);
        Page<DmBaseBriefVo> page = dmBaseMapper.selectDmBasePage(pageQuery.build(), bo);
        return TableDataInfo.build(page);
    }


    @Override
    public List<DmBaseVo> queryList(DmBaseQueryBo bo){
        LambdaQueryWrapper<DmBase> lqw = buildQueryWrapper(bo);
        List<DmBaseVo> list = dmBaseMapper.selectVoList(lqw);
        return list;
    }

    /**
     * 查询地名属性信息
     */
    @Override
    public DmBaseComplexVo queryById(String id){

        DmBaseComplexVo vo=new DmBaseComplexVo();
        //直接调用selectVoById会导致dmlb不显示。实体string型，vo int型。
        //DmBase base=dmBaseMapper.selectById(id);
       // DmBaseVo baseVo= BeanUtil.toBean(base, DmBaseVo.class);
        DmBaseVo baseVo=dmBaseMapper.getInfo(id);
        if(baseVo!=null){
            vo.setBase(baseVo);
            vo.setGeo(geoMapper.queryGeoFile(baseVo.getCode()));
            DmFjVo fjVo= new DmFjVo();
            DmFjVo dmfj =fjMapper.selectVoOne(new LambdaQueryWrapper<DmFj>().eq(DmFj::getCode,baseVo.getCode()));
            if(ObjectUtil.isNotEmpty(dmfj)){
                fjVo=dmfj;
            }
            List<DmNameFileVo> nameFile=nameFileMapper.selectDmFileByCode(baseVo.getCode());
            if(!nameFile.isEmpty()){
                //批复文件
                fjVo.setPfwj(nameFile.get(0).getPfwjUrl());
            }
            vo.setFile(fjVo);
            //获取实体类
            ISpatialAttrBaseService spatialService= SpatialAttrFactory.getGeoAttrBaseService("base-"+baseVo.getDmlb().toString());
            if(spatialService!=null){
                vo.setSpatial(spatialService.getAttributeByCode(baseVo.getCode()));
            }
        }
        return vo;
    }

    @Override
    public DmBaseFlowComplexVo queryFlowById(String id){

        DmBaseFlowComplexVo vo=new DmBaseFlowComplexVo();
        //直接调用selectVoById会导致dmlb不显示。实体string型，vo int型。
        DmBase base=dmBaseMapper.selectById(id);
        DmBaseFlowVo baseVo= BeanUtil.toBean(base, DmBaseFlowVo.class);
        if(baseVo!=null){
            vo.setBase(baseVo);
            DmGeoVo geo= geoMapper.queryGeoFile(baseVo.getCode());
            if(geo!=null){
                vo.setGeo(geo);
            }
            DmFjVo fjVo= new DmFjVo();
            DmFjVo fj= fjMapper.selectVoOne(new LambdaQueryWrapper<DmFj>().eq(DmFj::getCode,baseVo.getCode()));
            if(fj!=null){
                fjVo=fj;
            }
            List<DmNameFileVo> nameFile=nameFileMapper.selectDmFileByCode(baseVo.getCode());
            if(!nameFile.isEmpty()){
                fjVo.setPfwj(nameFile.get(0).getPfwjUrl());
            }
            vo.setFile(fjVo);
            //获取实体类
            ISpatialAttrBaseService spatialService= SpatialAttrFactory.getGeoAttrBaseService("base-"+baseVo.getDmlb().toString());
            vo.setSpatial(spatialService.getAttributeLabelByCode(baseVo.getCode()));
            //返回流程状态
            //WorkflowUtils.setStatusFieldValue(vo, id);
        }
        return vo;
    }



    /**
     * 新增地名属性信息
     */
    @Override
    public Boolean insertByBo(DmBaseComplexSaveBo bo) {
        DmBase add = BeanUtil.toBean(bo.getBase(), DmBase.class);
        validEntityBeforeSave(add);
        //登记日期
        add.setRegisterDate(DateTime.now());
        boolean flag = dmBaseMapper.insert(add) > 0;
        if(flag){
            // 专有属性
            JSONObject spatial= bo.getSpatial();
            // 矢量数据
            DmGeoSaveBo geo=bo.getGeo();
            if(geo!=null){
                geo.setCode(add.getCode());
                geo.setName(add.getName());
                geo.setDmlbdm(add.getDmlb());
            }
            //附件
            DmFj fj=BeanUtil.toBean(bo.getFile(), DmFj.class);
            if(fj!=null){
                fj.setCode(add.getCode());
            }
            if(bo.getGeo().getGeom()!=null){
                BaseDmlbVo dmlb=dmlbMapper.selectVoOne(new LambdaQueryWrapper<BaseDmlb>().eq(BaseDmlb::getCode,add.getDmlb()));
                //矢量数据为点类型
                if(dmlb.getType().equals("点")){
                    geoMapper.insertGeoPointEntity(geo);
                }else{
                    geoMapper.insertGeoLineEntity(geo);
                }
            }
            if(spatial!=null){
                saveSpatialAttribute(add.getCode(),"base-"+add.getDmlb(),spatial);
            }
            if(fj.getDmzp()!=null){
                fjMapper.insert(fj);
            }
        }
        return flag;
    }

    /**
     * 修改地名属性信息
     */
    @Override
    public Boolean updateByBo(DmBaseComplexSaveBo bo) {
        DmBase base = BeanUtil.toBean(bo.getBase(), DmBase.class);
        //登记日期
        base.setRegisterDate(DateTime.now());
        JSONObject spatial = bo.getSpatial();
        boolean flag=true;
        if(base!=null){
            flag=dmBaseMapper.updateById(base)>0;
        }
        // 更新矢量数据
        if(bo.getGeo().getGeom()!=null){
            DmGeoSaveBo geo=bo.getGeo();
            geo.setCode(base.getCode());
            geo.setName(base.getName());
            BaseDmlbVo dmlb=dmlbMapper.selectVoOne(new LambdaQueryWrapper<BaseDmlb>().eq(BaseDmlb::getCode,base.getDmlb()));
            //矢量数据为点类型
            if(dmlb.getType().equals("点")){
                geoMapper.updateGeoPointEntity(geo);
            }else{
                geoMapper.updateGeoLineEntity(geo);
            }
        }
        //更新专有属性
        if(spatial!=null) {
            updateSpatialAttribute(base.getCode(), "base-"+base.getDmlb(), spatial);
        }
        //更新附件
        if(bo.getFile().getDmzp()!=null){
            DmFj fj=BeanUtil.toBean(bo.getFile(), DmFj.class);
            fj.setCode(base.getCode());
            fjMapper.updateById(fj);
        }
        return flag;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave (DmBase entity){
        //TODO 做一些数据校验,如唯一约束
        DmBaseQueryBo bo=new DmBaseQueryBo();
        bo.setCode(entity.getCode());
        LambdaQueryWrapper<DmBase> lqw = buildQueryWrapper(bo);
        if(dmBaseMapper.selectVoList(lqw).size()>0){
            throw new ServiceException("地名编码已存在！") ;
        }
    }

    /**
     * 批量删除地名属性信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids) {

        return dmBaseMapper.deleteByIds(ids) > 0;
    }

    /**
     *  实体查询条件
     */
    private LambdaQueryWrapper<DmBase> buildQueryWrapper(DmBaseQueryBo bo) {
        LambdaQueryWrapper<DmBase> lqw = Wrappers.lambdaQuery();
        lqw.likeRight(StringUtils.isNotBlank(bo.getDmlb()), DmBase::getDmlb, bo.getDmlb());
        lqw.like(StringUtils.isNotBlank(bo.getName()), DmBase::getName, bo.getName());
        lqw.like(StringUtils.isNotBlank(bo.getCode()), DmBase::getCode, bo.getCode());
        lqw.like(StringUtils.isNotBlank(bo.getXzqh()), DmBase::getCode, bo.getXzqh());
        return lqw;
    }

    private void saveSpatialAttribute(String code,String dmlb,JSONObject spatial) {
        ISpatialAttrBaseService service = SpatialAttrFactory.getGeoAttrBaseService(dmlb);
        if (null == service) {
            throw new BaseException(String.format("不支持类型为%s的地理实体", dmlb));
        }
        Map<String, String> map = new HashMap<>();
        map.put("code", code);
        map.put("data", JSONObject.toJSONString(spatial));
        service.saveAttribute(map);
    }

    private void updateSpatialAttribute(String code,String dmlb,JSONObject spatial) {
        ISpatialAttrBaseService service = SpatialAttrFactory.getGeoAttrBaseService(dmlb);
        if (null == service) {
            throw new BaseException(String.format("不支持类型为%s的地理实体", dmlb));
        }
        Map<String, String> map = new HashMap<>();
        map.put("code", code);
        map.put("data", JSONObject.toJSONString(spatial));
        service.updateAttribute(map);

    }


    @Override
    public DmBaseBriefVo generateCode(DmBaseQueryBo bo) {
        String code="";
        if(dmBaseMapper.generatorCode(bo)!=null){
            code=dmBaseMapper.generatorCode(bo);
        }else{
            code=bo.getXzqh()+""+bo.getDmlb()+"000001";
        }
        DmBaseBriefVo vo=new DmBaseBriefVo();
        vo.setCode(code);
        return vo;
    }

    @Override
    public  TableDataInfo<DmStatVo> queryDmlbByXzq(String xzq) {
        return TableDataInfo.build(dmBaseMapper.queryDmlbNumByXzqh(xzq));
    }

    @Override
    public TableDataInfo<DmStatVo> queryQhdmByXzq(String xzq) {
        return TableDataInfo.build(dmBaseMapper.queryQhdmNumByXzqh(xzq));
    }




}
